package com.cff.springbootwork.async.service;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Service
public class AsyncService {
	private Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	AsyncTaskService asyncTaskService;

	@Autowired
	ThreadPoolService threadPoolService;

	/**
	 * 测试new Thread 异步任务
	 */
	public void asyncThread() {
		log.info("开始执行任务");
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		log.info("请求属性test为：{}", request.getAttribute("test"));

		Thread thread1 = new Thread(new Runnable() {
			public void run() {
				asyncTaskService.asyncTask();
			}
		});
		thread1.start();

		HttpServletRequest afterRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		log.info("任务提前执行完成，开始返回,请求属性test为：{}", afterRequest.getAttribute("test"));
	}

	/**
	 * 测试 线程池 异步任务
	 */
	public void asyncThreadPool() {
		log.info("开始执行任务");
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		log.info("请求属性test为：{}", request.getAttribute("test"));

		threadPoolService.execute(new Runnable() {
			public void run() {
				asyncTaskService.asyncTask();
			}
		});

		HttpServletRequest afterRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		log.info("任务提前执行完成，开始返回,请求属性test为：{}", afterRequest.getAttribute("test"));
	}

	/**
	 * 测试 线程池 异步任务 Future回调
	 */
	public void asyncFuturePool() {
		log.info("开始执行任务");
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		log.info("请求属性test为：{}", request.getAttribute("test"));

		Callable<String> callable = new Callable<String>() {
			@Override
			public String call() throws Exception {
				asyncTaskService.asyncTask();
				return "1111";
			}
		};

		Future<String> future = threadPoolService.submit(callable);

		try {
//			future.get(); // 阻塞函数，如果直接用，它就一直阻塞，就不是异步了。
			if (future.isDone()) {
				log.info("这么快就完成了？不可能！");
				String result = future.get();
				log.info("任务结果为：{}", result);
			}
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		} catch (ExecutionException e1) {
			e1.printStackTrace();
		}

		HttpServletRequest afterRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		log.info("任务提前执行完成，开始返回,请求属性test为：{}", afterRequest.getAttribute("test"));
	}

	/**
	 * 测试 @Async 对异步任务的支持
	 */
	@Async
	public void asyncTaskAnnotation() {
		asyncTaskService.asyncTask();
	}

	/**
	 * 测试 Spring的@Async 对异步任务的支持， 同一个类内的方法不能实现异步
	 */
	public void asyncSpringAnnotationOne() {
		log.info("开始执行任务");
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		log.info("请求属性test为：{}", request.getAttribute("test"));

		asyncTaskAnnotation();

		HttpServletRequest afterRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		log.info("任务提前执行完成，开始返回,请求属性test为：{}", afterRequest.getAttribute("test"));
	}

	/**
	 * 测试 Spring的@Async 对异步任务的支持， 不同类的方法可以实现异步
	 */
	public void asyncSpringAnnotationMuti() {
		log.info("开始执行任务");
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();

		log.info("请求属性test为：{}", request.getAttribute("test"));

		asyncTaskService.asyncTaskAnnotation();

		HttpServletRequest afterRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		log.info("任务提前执行完成，开始返回,请求属性test为：{}", afterRequest.getAttribute("test"));
	}

}
